<?php


namespace app\controller\admin;


use app\common\model\CacheRefreshHandler;
use app\common\service\face\FaceDevice;
use app\common\service\redis\PoolRedis;
use app\model\AdminStaff;
use app\model\AdminStaffIcCard;
use app\util\ExcelHandle;
use app\util\ReturnCode;
use app\util\Strs;
use app\util\Tools;
use think\exception\ValidateException;
use think\facade\Queue;
use think\facade\Request;
use think\Response;

/**
 * 职工列表
 */
class Staff extends Base
{
    public function index(): Response {
        $limit = $this->request->get('size', config('apiadmin.ADMIN_LIST_DEFAULT'));
        $start = $this->request->get('page', 1);
        $school_id = $this->request->get('school_id', $this->userInfo['school_id']);
        $keywords = $this->request->get('name', '');
        $phone = $this->request->get('phone', '');
        $sortKey = $this->request->get('sortKey', 'create_time');
        $order = $this->request->get('order', 'DESC');

        $where = [
            ['AdminStaff.is_delete', '=', 0],
            ['AdminStaff.type', '<>', AdminStaff::STUDENT]
        ];

        $obj = (new AdminStaff())->alias('AdminStaff');
        if ($keywords) {
            array_push($where, ['AdminStaff.name', 'like', "%{$keywords}%"]);
        }
        if ($phone) {
            array_push($where, ['AdminStaff.phone', '=', $phone]);
        }
        if ($school_id > 0) {
            array_push($where, ['AdminStaff.school_id', '=', $school_id]);
        }
        $listObj = $obj->where($where)->with(['school','staffData','icCard','icCard.student'])
            ->append(['status_text','type_text'])
            ->order('AdminStaff.'.$sortKey, $order)
            ->paginate(['page' => $start, 'list_rows' => $limit])->toArray();

        return $this->buildSuccess([
            'type'  => AdminStaff::TYPE_ARR,
            'list'  => $listObj['data'],
            'count' => $listObj['total']
        ]);
    }

    public function add(): Response {
        $school_id = Request::post('school_id/d');
        $name = Request::post('name/s', '', 'strip_tags');
        $type = Request::post('type/d');
        $sex = Request::post('sex/s');
        $phone = Request::post('phone/s');
        $password = Request::post('password/s');
        $face = Request::post('face/s');
        try {
            validate(\app\validate\AdminStaff::class)->scene('staff')->check(input('post.'));
        } catch (ValidateException $e) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $e->getError());
        }

        $staff = (new AdminStaff())->where([
            'is_delete' => 0,
            'phone' => $phone
        ])->findOrEmpty();
        if (!$staff->isEmpty()) {
            return $this->buildFailed(ReturnCode::DATA_EXISTS, '手机号已被使用');
        }

        if (empty($password)) {
            $password = substr($phone, -6);
        }
        $staff = new AdminStaff();

        $staff->school_id = $school_id;
        $staff->name = $name;
        $staff->type = $type;
        $staff->status = AdminStaff::AUDIT_PASS;
        $staff->sex = $sex;
        $staff->phone = $phone;
        $staff->password = Tools::userMd5($password);
        $staff->uuid = substr(Strs::uuid(), 1, -1);
        if (!empty($face)) {
            $fileName = $staff->uuid.".jpg"; // 首次新增使用 uuid
            if (FaceDevice::base64_image_content($face, app()->getRootPath() . 'public/upload/faces/', $fileName)) {
                $staff->face = '/upload/faces/'.$fileName;
            } else {
                return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '人脸图片保存失败');
            }
        }

        if (!$staff->save()) {
            return $this->buildFailed(ReturnCode::DB_SAVE_ERROR);
        }
        FaceDevice::editPerson($staff->id);// 更新人脸设备信息
        return $this->buildSuccess();
    }

    public function edit(): Response {
        $insert = input('post.');
        try {
            validate(\app\validate\AdminStaff::class)->scene('staff')->check($insert);
        } catch (ValidateException $e) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $e->getError());
        }

        $origin = AdminStaff::where('id', $insert['id'])->findOrEmpty();
        if ($origin->isEmpty()) {
            return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '账户未找到');
        }

        $staff = (new AdminStaff())->where([
            'is_delete' => 0,
            'phone' => $insert['phone']
        ])->where('id', '<>', $insert['id'])->findOrEmpty();
        if (!$staff->isEmpty()) {
            return $this->buildFailed(ReturnCode::DATA_EXISTS, '手机号已被使用');
        }

        if (empty($insert['password'])) {
            unset($insert['password']);
        } else {
            $insert['password'] = Tools::userMd5($insert['password']);
        }
        if ($insert['permission']) {
            $insert['permission'] = json_encode((array)$insert['permission'], JSON_UNESCAPED_UNICODE);
        }
        if (!empty($insert['face']) && preg_match('/^(data:\s*image\/(\w+);base64,)/', $insert['face'])) {
            $fileName = $insert['id'].".jpg";
            if (FaceDevice::base64_image_content($insert['face'], app()->getRootPath() . 'public/upload/faces/', $fileName)) {
                $insert['face'] = '/upload/faces/'.$fileName;
            } else {
                return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '人脸图片保存失败');
            }
        }
        $staff = AdminStaff::update($insert);
        if ($staff === false) {
            return $this->buildFailed(ReturnCode::DB_SAVE_ERROR);
        }
        FaceDevice::editPerson($staff->id);// 更新人脸设备信息
        CacheRefreshHandler::hIncrBy($staff->toArray(), $origin->toArray());
        return $this->buildSuccess();
    }

    /**
     * @func lockAuthorization
     * @method POST
     * @desc 职工门锁授权
     * @return Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @Time: 2021/12/30 16:23
     */
    public function lockAuthorization(): Response {
        $staff_id = Request::post('id/d');
        $selected = Request::post('selected/a');

        $select_id_arr = [];
        foreach ($selected as $item) {
            $select_id_arr[$item['id']] = $item['permission'];
        }
        if (!is_array($staff_id)) {
            $staff_id = [$staff_id];
        }
        $staffList = AdminStaff::where([
            'id' => $staff_id,
            'is_delete' => 0
        ])->field('id,smart_card')
            ->select()->toArray();
        $staff_id = array_column($staffList, 'id');
        // 删除职工未授权的宿舍楼
        $icCards = AdminStaffIcCard::where([
            'staff_id' => $staff_id,
            'is_delete' => 0
        ])->select();
        foreach ($icCards as $card) {
            if (!empty($select_id_arr[$card->student_dormitory_id])) {
                $card->lock_permission = implode(",", $select_id_arr[$card->student_dormitory_id]);
                $card->save();
                unset($select_id_arr[$card->student_dormitory_id]);
            } else {
                $card->is_delete = 1;
                $card->save();
            }
        }
        if (count($selected) > 0) {
            // 批量保存宿舍
            foreach ($staffList as $item) {
                AdminStaffIcCard::batchInsert($item['id'], $select_id_arr, $item['smart_card']);
            }
        }

        return $this->buildSuccess();
    }

    /**
     * @func import
     * @desc 导入职工信息
     * @return \think\Response
     * @Time: 2021/12/17 11:18
     */
    public function upload(): Response  {
        // 获取表单上传文件 例如上传了001.jpg
        $file = request()->file('excel_file');
        $school_id = request()->post('school_id');
        // 上传到本地服务器
        try {
            validate(['image'=>'fileSize:20480|fileExt:xls,xlsx'])
                ->check([$file]);
            $fileExtendName = substr(strrchr($file->getOriginalName(), '.'), 1);
            $filePath = $file->getPathname();
            if (is_file($filePath)){
                $cols = [['1' => 'number'],['2' =>'name'],['3' => 'sex'],['4' => 'phone'],['5' => 'type'],['6' => 'student_dormitory_id'],['7' => 'sim_card'],['8' => 'ic_card'], ['9' => 'blue_booth_rule'], ['10' => 'temp_pwd_rule'], ['11' => 'super_sim_rule'], ['12' => 'ic_card_rule']];
                $data = ExcelHandle::importExcel($filePath,$cols,$fileExtendName, 3);

                $redis = PoolRedis::instance();
                $redis->multi(\Redis::PIPELINE);
                foreach ($data as $datum) {
                    $datum['school_id'] = $school_id;
                    $datum['status'] = AdminStaff::AUDIT_PASS;
                    $datum['sim_card'] = trim($datum['sim_card']);
                    $datum['ic_card'] = trim($datum['ic_card']);
                    $redis->lPush("upload_staff", serialize($datum));
                }
                $redis->exec();
                Queue::push('app\task\job\UploadSyncHandlerJob@fire', [
                    'model'=> AdminStaff::class,
                    'action' => 'upload_staff'
                ]);
            }
            return $this->buildSuccess();
        } catch (\think\exception\ValidateException $e) {
            return $this->buildFailed(ReturnCode::FILE_SAVE_ERROR, $e->getMessage());
        }
    }

    /**
     * @func download
     * @desc 导出文件
     * @return \think\Response
     * @Time: 2021/12/17 11:18
     */
    public function download(): Response  {
        $titles = [['id' => '序号'],['school_name' => '学校名称'],['name'=>'姓名'],['type_text'=>'岗位'],['sex' => '性别'],['phone' => '手机号码'],['dormitory_name_list' => '已授权宿舍楼'],['student_dormitory_name_list' => '已授权宿舍']];

        $school_id = $this->request->get('school_id', 0);
        $keywords = $this->request->get('name', '');
        $phone = $this->request->get('phone', '');

        try {
            $where = [
                ['AdminStaff.is_delete', '=', 0],
                ['AdminStaff.type', 'in', [AdminStaff::STAFF, AdminStaff::GATEKEEPER]]
            ];

            $obj = (new AdminStaff())->alias('AdminStaff');
            if ($keywords) {
                array_push($where, ['AdminStaff.name', 'like', "%{$keywords}%"]);
            }
            if ($phone) {
                array_push($where, ['AdminStaff.phone', '=', $phone]);
            }
            if ($school_id > 0) {
                array_push($where, ['AdminStaff.school_id', '=', $school_id]);
            }
            $listObj = $obj->where($where)->with(['school','class','icCard'=>['student', 'dormitory']])
                ->append(['type_text'])
                ->order('AdminStaff.create_time', 'DESC')
                ->select()->toArray();
            $exportData = [];
            $len = 1;
            foreach ($listObj as $datum) {
                $datum['student_no'] .= "\t";
                $datum['id_card'] .= "\t";
                $datum['phone'] .= "\t";
                $datum['entrance_time'] .= "\t";

                $dormitory_name = [];
                $student_dormitory_name = [];
                if ($datum['icCard']) {
                    foreach ($datum['icCard'] as $card) {
                        $dormitory_name[] = $card['dormitory_name'];
                        $student_dormitory_name[] = $card['student_dormitory_name'];
                    }
                }
                $datum['dormitory_name_list'] = join(',',array_unique($dormitory_name))."\t";
                $datum['student_dormitory_name_list'] = join(',',array_unique($student_dormitory_name))."\t";

                $newItem = array_merge(['id' => $len],$datum);
                array_push($exportData, $newItem);
                $len++;
            }
            ExcelHandle::downLoadExcel('职工信息' . date('YmdHi'), $titles, $exportData);

        } catch (\think\exception\ValidateException $e) {
            return $this->buildFailed(ReturnCode::FILE_SAVE_ERROR, $e->getMessage());
        }
    }
}